﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using ZP.IDAL;

namespace ZP.DAL
{
    public partial class BaseRepository<T, TKey> : IBaseRepository<T, TKey> where T : class, new()
    {
        protected DbContext dbContext = DbContextFactory.Create();
        
        protected bool disposedValue;
        //参考 https://blog.csdn.net/weixin_30411239/article/details/97632834
        //https://www.bbsmax.com/A/n2d92XD4zD/

        public DbContext GetDbContext()
        {
            return dbContext;
        }

        public T Find(TKey id)
        {
            return dbContext.Set<T>().Find(id);
        }

        public T Find(Expression<Func<T, bool>> WhereLambda)
        {
            return dbContext.Set<T>().AsNoTracking().Where(WhereLambda).FirstOrDefault();
        }

        public void Add(T entity, bool isSaveChage = true)
        {
            dbContext.Set<T>().Add(entity);
            if (isSaveChage)
            {
                SaveChanges();
            }
        }

        public virtual bool Update(T entity, bool isSaveChage = true)
        {
            dbContext.Entry(entity).State = EntityState.Modified;
            if (isSaveChage)
            {
                SaveChanges();
            }
            return true;
        }

        public virtual bool Delete(T entity, bool isSaveChage = true)
        {
            dbContext.Entry(entity).State = EntityState.Deleted;
            if (isSaveChage)
            {
                SaveChanges();
            }
            return true;
        }

        public virtual int Delete(params TKey[] ids)
        {
            foreach (var item in ids)
            {
                var entity = dbContext.Set<T>().Find(item);
                dbContext.Set<T>().Remove(entity);
            }
            SaveChanges();
            return ids.Count();
        }

        public IQueryable<T> GetModels(Expression<Func<T, bool>> whereLambda)
        {
            return dbContext.Set<T>().Where(whereLambda).AsQueryable();
        }

        public IQueryable<T> GetModelsByPage<type>(int pageSize, int pageIndex, out int total, Expression<Func<T, bool>> WhereLambda, Expression<Func<T, type>> OrderByLambda, bool isAsc)
        {
            total = dbContext.Set<T>().Where(WhereLambda).Count();
            if (isAsc)
            {
                return
                dbContext.Set<T>()
                  .Where(WhereLambda)
                  .OrderBy(OrderByLambda)
                  .Skip(pageSize * (pageIndex - 1))
                  .Take(pageSize)
                  .AsQueryable();
            }
            else
            {
                return
               dbContext.Set<T>()
                 .Where(WhereLambda)
                 .OrderByDescending(OrderByLambda)
                 .Skip(pageSize * (pageIndex - 1))
                 .Take(pageSize)
                 .AsQueryable();
            }
        }

        public bool SaveChanges()
        {
            return dbContext.SaveChanges() > 0;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    dbContext?.Dispose();
                }
                disposedValue = true;
            }
        }

        public void Dispose()
        {
            Dispose(true);
        }
    }
}
